/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.bpm.engine.impl.util;

import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Strings;
import com.je.bpm.common.identity.ActivitiDepartment;
import com.je.bpm.common.operation.OperatorEnum;
import com.je.bpm.core.model.*;
import com.je.bpm.core.model.config.CustomEvent;
import com.je.bpm.core.model.config.process.ProcessBasicConfigImpl;
import com.je.bpm.core.model.config.task.TaskApprovalNoticeConfigImpl;
import com.je.bpm.core.model.event.StartEvent;
import com.je.bpm.core.model.message.Message;
import com.je.bpm.core.model.process.EventSubProcess;
import com.je.bpm.core.model.process.Process;
import com.je.bpm.core.model.task.KaiteBaseUserTask;
import com.je.bpm.core.model.task.KaiteCounterSignUserTask;
import com.je.bpm.core.model.task.KaiteMultiUserTask;
import com.je.bpm.engine.ActivitiException;
import com.je.bpm.engine.approvalnotice.TaskApprovalNoticeEnum;
import com.je.bpm.engine.delegate.DelegateExecution;
import com.je.bpm.engine.delegate.Expression;
import com.je.bpm.engine.delegate.event.ActivitiEventDispatcher;
import com.je.bpm.engine.delegate.event.ActivitiEventType;
import com.je.bpm.engine.delegate.event.impl.ActivitiEventBuilder;
import com.je.bpm.engine.impl.context.Context;
import com.je.bpm.engine.impl.el.ExpressionManager;
import com.je.bpm.engine.impl.identity.Authentication;
import com.je.bpm.engine.impl.interceptor.CommandContext;
import com.je.bpm.engine.impl.persistence.entity.ExecutionEntity;
import com.je.bpm.engine.impl.persistence.entity.MessageEventSubscriptionEntity;
import com.je.bpm.engine.repository.ProcessDefinition;
import com.je.bpm.engine.runtime.ProcessInstance;
import com.je.bpm.runtime.shared.dto.EventSubmitDTO;

import java.text.SimpleDateFormat;
import java.util.*;

public class ProcessInstanceHelper {

    public static final String DAFAULT_DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

    public static final String DAFAULT_DATE_FORMAT = "yyyy-MM-dd";

    private static SimpleDateFormat datetimeFormat = new SimpleDateFormat(DAFAULT_DATETIME_FORMAT);

    private static SimpleDateFormat dateFormat = new SimpleDateFormat(DAFAULT_DATE_FORMAT);

    public ProcessInstance createAndStartProcessInstance(ProcessDefinition processDefinition, String businessKey, String processInstanceName, Map<String, Object> variables, Map<String, Object> transientVariables) {
        return createAndStartProcessInstance(processDefinition, businessKey, processInstanceName, variables, transientVariables, true);
    }

    public Process getActiveProcess(ProcessDefinition processDefinition) {
        if (ProcessDefinitionUtil.isProcessDefinitionSuspended(processDefinition.getId())) {
            throw new ActivitiException("Cannot start process instance. Process definition " + processDefinition.getName() + " (id = " + processDefinition.getId() + ") is suspended");
        }
        Process process = ProcessDefinitionUtil.getProcess(processDefinition.getId());
        if (process == null) {
            throw new ActivitiException("Cannot start process instance. Process model " + processDefinition.getName() + " (id = " + processDefinition.getId() + ") could not be found");
        }
        return process;
    }

    public FlowElement getInitialFlowElement(Process process, String processDefinitionID) {
        FlowElement initialFlowElement = process.getInitialFlowElement();
        if (initialFlowElement == null) {
            throw new ActivitiException("No start element found for process definition " + processDefinitionID);
        }
        return initialFlowElement;
    }

    protected ProcessInstance createAndStartProcessInstance(ProcessDefinition processDefinition, String businessKey, String processInstanceName, Map<String, Object> variables, Map<String, Object> transientVariables, boolean startProcessInstance) {
        Process process = this.getActiveProcess(processDefinition);
        FlowElement initialFlowElement = this.getInitialFlowElement(process, processDefinition.getId());
        return createAndStartProcessInstanceWithInitialFlowElement(processDefinition, businessKey,
                processInstanceName, initialFlowElement, process, variables, transientVariables, startProcessInstance);
    }

    public ProcessInstance createProcessInstance(ProcessDefinition processDefinition, String businessKey, String processInstanceName, Map<String, Object> variables, Map<String, Object> transientVariables) {
        Process process = this.getActiveProcess(processDefinition);
        FlowElement initialFlowElement = this.getInitialFlowElement(process, processDefinition.getId());
        ExecutionEntity processInstance = createProcessInstanceWithInitialFlowElement(processDefinition,
                businessKey,
                processInstanceName,
                initialFlowElement,
                process);
        return processInstance;
    }

    public ProcessInstance createAndStartProcessInstanceByMessage(ProcessDefinition processDefinition, String businessKey, String messageName, Map<String, Object> messageVariables, Map<String, Object> transientVariables) {
        Process process = this.getActiveProcess(processDefinition);

        FlowElement initialFlowElement = null;
        BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processDefinition.getId());
        for (FlowElement flowElement : process.getFlowElements()) {
            if (flowElement instanceof StartEvent) {
                StartEvent startEvent = (StartEvent) flowElement;
                if (CollectionUtil.isNotEmpty(startEvent.getEventDefinitions()) && startEvent.getEventDefinitions().get(0) instanceof MessageEventDefinition) {

                    MessageEventDefinition messageEventDefinition = (MessageEventDefinition) startEvent.getEventDefinitions().get(0);
                    String messageRef = messageEventDefinition.getMessageRef();
                    if (messageRef.equals(messageName)) {
                        initialFlowElement = flowElement;
                        break;
                    } // FIXME: We should not need to reset eventDefinition messageRef to message name
                    else if (bpmnModel.containsMessageId(messageRef)) {
                        Message message = bpmnModel.getMessage(messageRef);
                        messageEventDefinition.setMessageRef(message.getName());
                        initialFlowElement = flowElement;
                        break;
                    }
                }
            }
        }
        if (initialFlowElement == null) {
            throw new ActivitiException("No message start event found for process definition " + processDefinition.getId() + " and message name " + messageName);
        }

        Map<String, Object> processVariables = messageVariables;

        // Create process instance with executions but defer to start process after dispatching ACTIVITY_MESSAGE_RECEIVED
        ExecutionEntity processInstance = createProcessInstanceWithInitialFlowElement(processDefinition,
                businessKey,
                null,
                initialFlowElement,
                process);

        // Dispatch message received event
        dispatchStartMessageReceivedEvent(processInstance, messageName, messageVariables);

        // Finally start the process
        CommandContext commandContext = Context.getCommandContext();
        startProcessInstance(processInstance, commandContext, processVariables, initialFlowElement, transientVariables);

        return processInstance;
    }

    private void updateProcessInstanceStartDate(ExecutionEntity processInstance) {
        CommandContext commandContext = Context.getCommandContext();
        commandContext.getExecutionEntityManager().updateProcessInstanceStartDate(processInstance);
    }

    public ProcessInstance createAndStartProcessInstanceWithInitialFlowElement(ProcessDefinition processDefinition,
                                                                               String businessKey, String processInstanceName, FlowElement initialFlowElement,
                                                                               Process process, Map<String, Object> variables, Map<String, Object> transientVariables, boolean startProcessInstance) {

        ExecutionEntity processInstance = createProcessInstanceWithInitialFlowElement(processDefinition,
                businessKey,
                processInstanceName,
                initialFlowElement,
                process);
        if (startProcessInstance) {
            CommandContext commandContext = Context.getCommandContext();
            startProcessInstance(processInstance, commandContext, variables, initialFlowElement, transientVariables);
        }

        return processInstance;
    }

    private void recordStartProcessInstance(CommandContext commandContext, FlowElement initialFlowElement, ExecutionEntity processInstance) {
        updateProcessInstanceStartDate(processInstance);
        commandContext.getHistoryManager().recordProcessInstanceStart(processInstance, initialFlowElement);
    }

    private void createProcessVariables(ExecutionEntity processInstance,
                                        Map<String, Object> variables, Map<String, Object> transientVariables,
                                        Process process) {
        processInstance.setVariables(processDataObjects(process.getDataObjects()));
        // Set the variables passed into the start command
        if (variables != null) {
            for (String varName : variables.keySet()) {

                processInstance.setVariable(varName, variables.get(varName));
            }
        }
        if (transientVariables != null) {
            for (String varName : transientVariables.keySet()) {
                processInstance.setTransientVariable(varName, transientVariables.get(varName));
            }
        }
        // Fire events
        if (Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
            Context.getProcessEngineConfiguration()
                    .getEventDispatcher()
                    .dispatchEvent(ActivitiEventBuilder.createEntityWithVariablesEvent(ActivitiEventType.ENTITY_INITIALIZED,
                            processInstance,
                            variables,
                            false));
        }
    }

    public void startProcessInstance(ExecutionEntity processInstance, CommandContext commandContext, Map<String, Object> variables, FlowElement initialFlowElement, Map<String, Object> transientVariables) {
        Process process = ProcessDefinitionUtil.getProcess(processInstance.getProcessDefinitionId());
        createProcessVariables(processInstance, variables, transientVariables, process);
        recordStartProcessInstance(commandContext, initialFlowElement, processInstance);

        // Event sub process handling
        List<MessageEventSubscriptionEntity> messageEventSubscriptions = new LinkedList<>();
        for (FlowElement flowElement : process.getFlowElements()) {
            if (flowElement instanceof EventSubProcess) {
                EventSubProcess eventSubProcess = (EventSubProcess) flowElement;
                for (FlowElement subElement : eventSubProcess.getFlowElements()) {
                    if (subElement instanceof StartEvent) {
                        StartEvent startEvent = (StartEvent) subElement;
                        if (CollectionUtil.isNotEmpty(startEvent.getEventDefinitions())) {
                            EventDefinition eventDefinition = startEvent.getEventDefinitions().get(0);
                            if (eventDefinition instanceof MessageEventDefinition) {
                                MessageEventDefinition messageEventDefinition = (MessageEventDefinition) eventDefinition;
                                BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processInstance.getProcessDefinitionId());
                                if (bpmnModel.containsMessageId(messageEventDefinition.getMessageRef())) {
                                    messageEventDefinition.setMessageRef(bpmnModel.getMessage(messageEventDefinition.getMessageRef()).getName());
                                }
                                ExecutionEntity messageExecution = commandContext.getExecutionEntityManager().createChildExecution(processInstance);
                                messageExecution.setCurrentFlowElement(startEvent);
                                messageExecution.setEventScope(true);

                                String messageName = getMessageName(commandContext,
                                        messageEventDefinition,
                                        messageExecution);

                                MessageEventSubscriptionEntity subscription = commandContext.getEventSubscriptionEntityManager()
                                        .insertMessageEvent(messageName,
                                                messageExecution);
                                Optional<String> correlationKey = getCorrelationKey(commandContext,
                                        messageEventDefinition,
                                        messageExecution);
                                correlationKey.ifPresent(subscription::setConfiguration);

                                messageEventSubscriptions.add(subscription);
                            }
                        }
                    }
                }
            }
        }

        ExecutionEntity execution = processInstance.getExecutions().get(0); // There will always be one child execution created

        execution.setAppVersion(processInstance.getAppVersion());

        commandContext.getAgenda().planContinueProcessOperation(execution);

        if (Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
            ActivitiEventDispatcher eventDispatcher = Context.getProcessEngineConfiguration().getEventDispatcher();
            eventDispatcher.dispatchEvent(ActivitiEventBuilder.createProcessStartedEvent(execution, variables, false));

            for (MessageEventSubscriptionEntity messageEventSubscription : messageEventSubscriptions) {
                commandContext.getProcessEngineConfiguration().getEventDispatcher()
                        .dispatchEvent(ActivitiEventBuilder.createMessageWaitingEvent(messageEventSubscription.getExecution(),
                                messageEventSubscription.getEventName(),
                                messageEventSubscription.getConfiguration()));
            }
        }
    }

    protected Map<String, Object> processDataObjects(Collection<ValuedDataObject> dataObjects) {
        Map<String, Object> variablesMap = new HashMap<String, Object>();
        // convert data objects to process variables
        if (dataObjects != null) {
            for (ValuedDataObject dataObject : dataObjects) {
                variablesMap.put(dataObject.getName(), dataObject.getValue());
            }
        }
        return variablesMap;
    }

    protected Optional<String> getCorrelationKey(CommandContext commandContext,
                                                 MessageEventDefinition messageEventDefinition,
                                                 DelegateExecution execution) {
        ExpressionManager expressionManager = commandContext.getProcessEngineConfiguration()
                .getExpressionManager();

        return Optional.ofNullable(messageEventDefinition.getCorrelationKey())
                .map(correlationKey -> {
                    Expression expression = expressionManager.createExpression(messageEventDefinition.getCorrelationKey());
                    return expression.getValue(execution).toString();
                });
    }

    protected String getMessageName(CommandContext commandContext, MessageEventDefinition messageEventDefinition, DelegateExecution execution) {
        ExpressionManager expressionManager = commandContext.getProcessEngineConfiguration()
                .getExpressionManager();
        String messageName = Optional.ofNullable(messageEventDefinition.getMessageRef())
                .orElse(messageEventDefinition.getMessageExpression());
        Expression expression = expressionManager.createExpression(messageName);
        return expression.getValue(execution).toString();
    }


    public ExecutionEntity createProcessInstanceWithInitialFlowElement(ProcessDefinition processDefinition, String businessKey, String processInstanceName, FlowElement initialFlowElement, Process process) {
        CommandContext commandContext = Context.getCommandContext();
        // Create the process instance
        String initiatorVariableName = null;
        if (initialFlowElement instanceof StartEvent) {
            initiatorVariableName = ((StartEvent) initialFlowElement).getInitiator();
        }
        //创建流程实例执行
        ExecutionEntity processInstance = commandContext.getExecutionEntityManager()
                .createProcessInstanceExecution(processDefinition,
                        businessKey,
                        processDefinition.getTenantId(),
                        initiatorVariableName);

        // Set processInstance name
        setProcessInstanceName(commandContext, processInstance, processInstanceName);

        // Create the first execution that will visit all the process definition elements
        ExecutionEntity execution = commandContext.getExecutionEntityManager().createChildExecution(processInstance);
        execution.setCurrentFlowElement(initialFlowElement);

        return processInstance;
    }

    private void setProcessInstanceName(CommandContext commandContext, ExecutionEntity processInstance, String processInstanceName) {
        if (processInstanceName != null) {
            processInstance.setName(processInstanceName);
            commandContext.getHistoryManager()
                    .recordProcessInstanceNameChange(processInstance.getId(), processInstanceName);
        }
    }

    protected void dispatchStartMessageReceivedEvent(ExecutionEntity processInstance,
                                                     String messageName,
                                                     Map<String, Object> variables) {
        // Dispatch message received event
        if (Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
            // There will always be one child execution created
            DelegateExecution execution = processInstance.getExecutions().get(0);
            ActivitiEventDispatcher eventDispatcher = Context.getProcessEngineConfiguration()
                    .getEventDispatcher();
            eventDispatcher.dispatchEvent(ActivitiEventBuilder.createMessageReceivedEvent(execution,
                    messageName,
                    null,
                    variables));
        }
    }

    public Map<String, Object> buildStartBeanInfo(Map<String, Object> bean) {
        bean.put("SY_STARTEDUSER", Authentication.getAuthenticatedUser().getDeptId());
        bean.put("SY_STARTEDUSERNAME", Authentication.getAuthenticatedUser().getName());
        bean.put("SY_LASTFLOWUSER", Authentication.getAuthenticatedUser().getName());
        bean.put("SY_LASTFLOWUSERID", Authentication.getAuthenticatedUser().getDeptId());
        Context.getCommandContext().addAttribute(CommandContext.BEAN, bean);
        return bean;
    }

    public Map<String, Object> buildRevokeBeanInfo(Map<String, Object> bean) {
        bean.put("SY_STARTEDUSER", "");
        bean.put("SY_STARTEDUSERNAME", "");
        bean.put("SY_APPROVEDUSERS", "");
        bean.put("SY_APPROVEDUSERNAMES", "");
        bean.put("SY_PREAPPROVUSERS", "");
        bean.put("SY_LASTFLOWINFO", "");
        bean.put("SY_PREAPPROVUSERNAMES", "");
        bean.put("SY_LASTFLOWUSER", "");
        bean.put("SY_LASTFLOWUSERID", "");
        bean.put("SY_WFWARN", "");
        bean.put("SY_WFWARN", "");
        bean.put("SY_WARNFLAG", "");
        bean.put("SY_CURRENTTASK", "");
        bean.put("SY_AUDFLAG", "NOSTATUS");
        return bean;
    }

    /**
     * 修改bean状态
     */
    public void updateBeanInfo(ProcessBasicConfigImpl processBasicConfig, String businessKey,
                               String type, CommandContext commandContext) {
        Map<String, Object> bean = (Map<String, Object>) commandContext.getAttribute(CommandContext.BEAN);
        if (bean == null) {
            return;
        }
        if (!Strings.isNullOrEmpty(type)) {
            bean.put("SY_AUDFLAG", type);
        }
        commandContext.updateBean(bean, businessKey, processBasicConfig);
    }


    public void buildProcessCustomerFileSetValue(CommandContext commandContext, CustomEvent customEvent,
                                                 CustomEvent.CustomEventEnum type, String comment,
                                                 Map<String, Object> bean) {
        if (bean == null) {
            return;
        }
        String assignmentFieldConfiguration = customEvent.getAssignmentFieldConfiguration();
        if (Strings.isNullOrEmpty(assignmentFieldConfiguration)) {
            return;
        }
        String[] assignmentFieldConfigurationArray = assignmentFieldConfiguration.split(",");
        if (assignmentFieldConfigurationArray.length != 2) {
            return;
        }
        String fieldConfigInfoKey = assignmentFieldConfigurationArray[0];
        String fieldConfigInfoValue = assignmentFieldConfigurationArray[1];
        String[] fieldConfigInfoKeyArray = fieldConfigInfoKey.split("~");
        String[] fieldConfigInfoValueArray = fieldConfigInfoValue.split("~");
        for (int i = 0; i < fieldConfigInfoKeyArray.length; i++) {
            String fieldCode = fieldConfigInfoKeyArray[i];
            String value = fieldConfigInfoValueArray[i];
            bean.put(fieldCode, getCustomerValue(commandContext, value, comment, type.getName()));
        }

        commandContext.addAttribute(CommandContext.BEAN, bean);
    }

    public String getCustomerValue(CommandContext commandContext, String value, String comment, String submitType) {
        ActivitiDepartment activitiDepartment = commandContext.getProcessEngineConfiguration().getUserDepartmentManager()
                .findLogUserDepartment();
        if (value.equals("''")) {//空
            return "";
        } else if (value.equals("@SUBMIT_TRAN@")) {//审批动作
            return submitType;
        } else if (value.equals("@SUBMIT_COMENTS@")) {//审批意见
            return comment;
        } else if (value.equals("@USER_NAME@")) {//登录用户
            return Authentication.getAuthenticatedUser().getName();
        } else if (value.equals("@USER_CODE@")) {//登录用户编码
            return Authentication.getAuthenticatedUser().getCode();
        } else if (value.equals("@USER_ID@")) {//登录用户ID
            return Authentication.getAuthenticatedUser().getId();
        } else if (value.equals("@DEPT_NAME@")) {//登录用户所在部门
            return activitiDepartment.getName();
        } else if (value.equals("@DEPT_CODE@")) {//登录用户所在部门编码
            return activitiDepartment.getCode();
        } else if (value.equals("@DEPT_ID@")) {//登录用户所在部门ID
            return activitiDepartment.getId();
        } else if (value.equals("@NOW_DATE@")) {//当前日期(年月日)
            return formatDate(new Date());
        } else if (value.equals("@NOW_TIME@")) {//当前日期(年月日时分秒)
            return formatDateTime(new Date());
        }
        return value;
    }

    public static String formatDate(Date d) {
        if (d == null) {
            return "";
        }
        return dateFormat.format(d);
    }

    public static String formatDateTime(Date d) {
        if (d == null) {
            return "";
        }
        return datetimeFormat.format(d);
    }

    public void invokeEvent(List<CustomEvent> list, String taskName, String taskKey, String targetId,
                            CustomEvent.CustomEventEnum type, CommandContext commandContext, String comment,
                            String taskId, OperatorEnum operatorType) {
        Map<String, Object> bean = (Map<String, Object>) commandContext.getAttribute(CommandContext.BEAN);

        //执行不同事件
        for (CustomEvent customEvent : list) {
            if (customEvent.getCustomeEventType().equals(type)) {
                if (customEvent.getExecutionStrategy().equals(CustomEvent.CustomExecutionStrategyEnum.EXECUTION_METHOD)) {
                    invokeCustomEvent(customEvent, taskName, taskKey, targetId, commandContext, comment, taskId
                            , operatorType, bean);
                } else if (customEvent.getExecutionStrategy().equals(CustomEvent.CustomExecutionStrategyEnum.FIELD_ASSIGNMENT)) {
                    buildProcessCustomerFileSetValue(commandContext, customEvent, type, comment, bean);
                } else if (customEvent.getExecutionStrategy().equals(CustomEvent.CustomExecutionStrategyEnum.EXECUTE_SQL_TEMPLATE)) {
                    invokeSqlTemplateEvent(customEvent, commandContext, bean);
                }
            }
        }
    }

    //执行SQL模板
    private void invokeSqlTemplateEvent(CustomEvent customEvent, CommandContext commandContext, Map<String, Object> bean) {
        //sql模板编码
        String serviceName = customEvent.getServiceName();
        //流程启动所在的业务服务
        String prod = (String) commandContext.getAttribute(CommandContext.PROD);
        commandContext.getProcessEngineConfiguration().getRemoteCallServeManager().executeCustomSqlTemplate(prod, serviceName, bean);

    }

    //执行自定义事件
    public void invokeCustomEvent(CustomEvent customEvent, String taskName, String taskKey, String targetId,
                                  CommandContext commandContext, String comment,
                                  String taskId, OperatorEnum operatorType, Map<String, Object> bean) {
        String prod = (String) commandContext.getAttribute(CommandContext.PROD);

        EventSubmitDTO eventSubmitDTO = null;
        List<Map<String, String>> assignees = new ArrayList<>();
        String id = Authentication.getAuthenticatedUser().getDeptId();
        String userName = Authentication.getAuthenticatedUser().getName();
        Map<String, String> user = new HashMap<>();
        user.put("userId", id);
        user.put("userName", userName);
        assignees.add(user);
        eventSubmitDTO = EventSubmitDTO.build(taskId, taskName, taskKey, targetId,
                operatorType, comment, assignees, bean);
        String serviceName = customEvent.getServiceName();
        commandContext.getProcessEngineConfiguration().getRemoteCallServeManager().executeCustomMethod(eventSubmitDTO, prod, serviceName);
    }


    /**
     * 添加审批告知变量
     */
    public void addApprovalNotificationVariable(BpmnModel bpmnModel, String activityId, String comment, String submitType) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("assignee", Authentication.getAuthenticatedUser().getDeptId());
        jsonObject.put("comment", comment);
        jsonObject.put("submitType", submitType);
        jsonObject.put("taskId", activityId);
        //是否多人
        FlowElement flowElement = bpmnModel.getFlowElement(activityId);
        Boolean isMulti = false;
        if (flowElement instanceof KaiteBaseUserTask) {
            KaiteBaseUserTask kaiteBaseUserTask = (KaiteBaseUserTask) flowElement;
            if ((kaiteBaseUserTask instanceof KaiteCounterSignUserTask) || (kaiteBaseUserTask instanceof KaiteMultiUserTask)) {
                isMulti = true;
            }
            if (kaiteBaseUserTask.hasMultiInstanceLoopCharacteristics()) {
                isMulti = true;
            }
        }
        jsonObject.put("isMulti", isMulti);
        //审批告知类型
        List<TaskApprovalNoticeEnum> taskApprovalNoticeEnumList = new ArrayList<>();
        if (flowElement instanceof KaiteBaseUserTask) {
            //获取节点上审批告知的配置信息
            TaskApprovalNoticeConfigImpl taskApprovalNoticeConfig = ((KaiteBaseUserTask) flowElement).getTaskApprovalNoticeConfig();
            //判断是否是流程发起人收到通知
            if (taskApprovalNoticeConfig.isStartUser()) {
                taskApprovalNoticeEnumList.add(TaskApprovalNoticeEnum.STARTUSER);
            }
            //判断是否是已审批人员收到通知
            if (taskApprovalNoticeConfig.isApprovedPerson()) {
                taskApprovalNoticeEnumList.add(TaskApprovalNoticeEnum.APPROVEDPERSON);
            }
            //判断是否是直属领导收到通知
            if (taskApprovalNoticeConfig.isApproverDirectLeader()) {
                taskApprovalNoticeEnumList.add(TaskApprovalNoticeEnum.APPROVERDIRECTLEADER);
            }
            //判断是否是部门领导收到通知
            if (taskApprovalNoticeConfig.isApproverDeptLeader()) {
                taskApprovalNoticeEnumList.add(TaskApprovalNoticeEnum.APPROVERDEPTLEADER);
            }
        }
        if (taskApprovalNoticeEnumList.size() == 0) {
            return;
        }
        jsonObject.put("approvalNoticeType", taskApprovalNoticeEnumList);
        Context.getCommandContext().addAttribute(CommandContext.APPROVALNOTICE, jsonObject);
    }


}
